home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #31 / NN_1992_31.iso / bin / mac / mac_sit.hqx / Mac Stuff / NNTP Server (SAMPLE CODE) / NNTP Server.c next >
Encoding:
C/C++ Source or Header  |  1992-05-22  |  51.9 KB  |  2,095 lines

  1. /********************************************************\
  2.  *                                                        *
  3.  *    NNTP local Macintosh Server.                        *
  4.  *                                                        *
  5. /********************************************************/   
  6.  
  7. #include "NNTP Server.h"
  8. #include <stdio.h>
  9. #include <string.h>
  10.  
  11. short                netNewsDrive;                        /* Drive # of NetNews drive */
  12. char                netNewsVolName[32];                    /* Volume name of NetNews data */
  13. short                netNewsVRefNum;                        /* Volume reference # */
  14. char                PathTransFSpec[256];                /* Path translation FSpec */
  15. char                activeFSpec[256];                    /* Active file FSpec */
  16. char                CurrentGroupFSpec[256];                /* Dir FSpec of current group */
  17. char                lastGroup[256] = "none ";            /* Last canonical group selected */
  18. char                lastISOgroup[256];                    /* Last ISO group selected */
  19. char                lastActiveEntry[256] = "none ";        /* Last entry from Active file */
  20. int                    TCP_DriverRefNum;                    /* MacTCP Driver reference number */
  21. TCPiopb                NNTP_PB;
  22. EventRecord            evt;
  23. char                msgText[100];
  24. WDS                    sendWDS;
  25. Boolean                running, gWNEImplemented, sessionActive;
  26. EventRecord            gTheEvent;
  27. MenuHandle            gAppleMenu, gFileMenu, gEditMenu;
  28. WindowPtr            myWindow;
  29. Rect                aRect;
  30. Rect                *rectPtr;
  31. char                rcvBuf[RCV_BUF_SIZE];
  32. char                xmtBuf[XMT_BUF_SIZE];
  33. unsigned short        bufLen;
  34.  
  35. /***************************************************************************\
  36. *                                                                            *
  37. *    Routine:    main                                                        *
  38. *                                                                            *
  39. *    Function:    Initialize the server and begin executing the main loop.    *
  40. *                                                                            *
  41. *    Inputs:        None                                                        *
  42. *                                                                            *
  43. *    Outputs:    None                                                        *
  44. *                                                                            *
  45. \***************************************************************************/
  46.  
  47. main()
  48. {
  49.     ToolBoxInit();
  50.     MenuBarInit();
  51.     TCPInit();
  52.     MainLoop();
  53. }
  54.  
  55. /***************************************************************************\
  56. *                                                                            *
  57. *    Routine:    MainLoop                                                    *
  58. *                                                                            *
  59. *    Function:    Establish a client connection and service requests.            *
  60. *                Continue until the user 'Quit's.                            *
  61. *                                                                            *
  62. *    Inputs:        None                                                        *
  63. *                                                                            *
  64. *    Outputs:    None                                                        *
  65. *                                                                            *
  66. \***************************************************************************/
  67.  
  68. MainLoop()
  69. {
  70.     running = TRUE;
  71.     while (running)
  72.     {
  73.         while (running)
  74.         {
  75.             PassiveOpen(&NNTP_PB, NNTP_SERVER);
  76.             sessionActive = FALSE;
  77.             while ((NNTP_PB.ioResult == inProgress) && running)
  78.             {
  79.                 HandleEvent();
  80.             }
  81.             if (NNTP_PB.ioResult == noErr)
  82.             {
  83.                 strcpy(rcvBuf, "INIT\r\n");
  84.                 sessionActive = TRUE;
  85.             }
  86.             while (sessionActive && running)
  87.             {
  88.                 HandleEvent();
  89.                 if (NNTP_PB.ioResult == noErr)
  90.                 {
  91.                     bufLen = NNTP_PB.csParam.receive.rcvBuffLen;
  92.                     ProcessBuffer((char *)&rcvBuf, bufLen);
  93.                     ReceiveTCP(&NNTP_PB, rcvBuf, RCV_BUF_SIZE);
  94.                 }
  95.                 if (TCPStatusCheck(NNTP_PB.tcpStream) != ESTABLISHED)
  96.                 {
  97.                     CleanUp();
  98.                     sessionActive = FALSE;
  99.                 }
  100.             }
  101.         }
  102.     }
  103.     CleanUp();
  104.     ExitToShell();
  105. }
  106.  
  107. /***************************************************************************\
  108. *                                                                            *
  109. *    Routine:    ProcessBuffer                                                *
  110. *                                                                            *
  111. *    Function:    Process a buffer that may contain one or more NNTP            *
  112. *                requests.                                                    *
  113. *                                                                            *
  114. *    Inputs:        Pointer to receive buffer, and length of buffer.            *
  115. *                                                                            *
  116. *    Outputs:    None                                                        *
  117. *                                                                            *
  118. \***************************************************************************/
  119.  
  120. ProcessBuffer(buf, len)
  121. char                *buf;
  122. unsigned short        len;
  123. {
  124. char        *src, *dst;
  125. char        cmdBuf[512];
  126. short        spaceFound;
  127.     
  128.     src = buf;
  129.     dst = buf;
  130.     buf[len] = 0;
  131.     spaceFound = FALSE;
  132.     while(*src != 0)
  133.     {
  134.         if ((*src == SPACE) || (*src == TAB))
  135.         {
  136.             spaceFound = TRUE;
  137.         }
  138.         if (spaceFound)
  139.         {
  140.             *dst++ = *src++;
  141.         }
  142.         else
  143.         {
  144.             *dst++ = toupper(*src++);
  145.         }
  146.     }
  147.     while (strlen(buf) > 1)
  148.     {
  149.         GetRequest(buf, cmdBuf);
  150.         ProcessRequest(cmdBuf);
  151.     }
  152. }
  153.  
  154. /***************************************************************************\
  155. *                                                                            *
  156. *    Routine:    GetRequest                                                    *
  157. *                                                                            *
  158. *    Function:    Return a request line from request buffer.                    *
  159. *                                                                            *
  160. *                                                                            *
  161. *    Inputs:        Pointer to receive buffer and cmdBuf.                        *
  162. *                                                                            *
  163. *    Outputs:    Adjusted buffer data and modified length.                    *
  164. *                                                                            *
  165. \***************************************************************************/
  166.  
  167. GetRequest(buf, cmdBuf)
  168. char            *buf, *cmdBuf;
  169. {
  170. char        *src, *dst;
  171.     
  172.     src = buf;
  173.     dst = cmdBuf;
  174.     while((*src != 0) && (*src != LF))
  175.     {
  176.         *dst++ = *src++;
  177.     }
  178.     *dst++ = *src++;        /* LF */
  179.     *dst = 0;
  180.     
  181.     dst = buf;
  182.     while(*src != 0)
  183.     {
  184.         *dst++ = *src++;
  185.     }
  186.     *dst = 0;
  187. }
  188.     
  189. /***************************************************************************\
  190. *                                                                            *
  191. *    Routine:    ProcessRequest                                                *
  192. *                                                                            *
  193. *    Function:    Process the following NNTP requests:                        *
  194. *                                                                            *
  195. *                INIT                                                        *
  196. *                ARTICLE                                                        *
  197. *                BODY                                                        *
  198. *                GROUP                                                        *
  199. *                HEAD                                                        *
  200. *                HELP                                                        *
  201. *                IHAVE                                                        *
  202. *                LAST                                                        *
  203. *                LIST                                                        *
  204. *                NEWGROUPS                                                    *
  205. *                NEWNEWS                                                        *
  206. *                NEXT                                                        *
  207. *                POST                                                        *
  208. *                QUIT                                                        *
  209. *                SLAVE                                                        *
  210. *                STAT                                                        *
  211. *                X... - Extensions                                            *
  212. *                                                                            *
  213. *    Inputs:        Pointer to receive buffer.                                    *
  214. *                                                                            *
  215. *    Outputs:    None                                                        *
  216. *                                                                            *
  217. \***************************************************************************/
  218.  
  219. ProcessRequest(cmdBuf)
  220. char        *cmdBuf;
  221. {
  222.     if (memcmp("INIT", cmdBuf, strlen("INIT")) == 0)
  223.     {
  224.         if (!InitServer())
  225.         {
  226.             CleanUp();
  227.             sessionActive = FALSE;
  228.         }
  229.     }
  230.     
  231.     if (memcmp("ARTICLE", cmdBuf, strlen("ARTICLE")) == 0)
  232.     {
  233.         ArticleCmd(cmdBuf);
  234.     }
  235.     
  236.     if (memcmp("BODY", cmdBuf, strlen("BODY")) == 0)
  237.     {
  238.         BodyCmd(cmdBuf);
  239.     }
  240.     
  241.     if (memcmp("GROUP", cmdBuf, strlen("GROUP")) == 0)
  242.     {
  243.         GroupCmd(cmdBuf);
  244.     }
  245.     
  246.     if (memcmp("HEAD", cmdBuf, strlen("HEAD")) == 0)
  247.     {
  248.         HeadCmd(cmdBuf);
  249.     }
  250.     
  251.     if (memcmp("HELP", cmdBuf, strlen("HELP")) == 0)
  252.     {
  253.         HelpCmd(cmdBuf);
  254.     }
  255.     
  256.     if (memcmp("IHAVE", cmdBuf, strlen("IHAVE")) == 0)
  257.     {
  258.         IhaveCmd(cmdBuf);
  259.     }
  260.     
  261.     if (memcmp("LAST", cmdBuf, strlen("LAST")) == 0)
  262.     {
  263.         LastCmd(cmdBuf);
  264.     }
  265.     
  266.     if (memcmp("LIST", cmdBuf, strlen("LIST")) == 0)
  267.     {
  268.         ListCmd(cmdBuf);
  269.     }
  270.     
  271.     if (memcmp("NEWGROUPS", cmdBuf, strlen("NEWGROUPS")) == 0)
  272.     {
  273.         NewGroupsCmd(cmdBuf);
  274.     }
  275.     
  276.     if (memcmp("NEWNEWS", cmdBuf, strlen("NEWNEWS")) == 0)
  277.     {
  278.         NewNewsCmd(cmdBuf);
  279.     }
  280.     
  281.     if (memcmp("NEXT", cmdBuf, strlen("NEXT")) == 0)
  282.     {
  283.         NextCmd(cmdBuf);
  284.     }
  285.     
  286.     if (memcmp("POST", cmdBuf, strlen("POST")) == 0)
  287.     {
  288.         PostCmd(cmdBuf);
  289.     }
  290.     
  291.     if (memcmp("QUIT", cmdBuf, strlen("QUIT")) == 0)
  292.     {
  293.         QuitCmd(cmdBuf);
  294.     }
  295.     
  296.     if (memcmp("SLAVE", cmdBuf, strlen("SLAVE")) == 0)
  297.     {
  298.         SlaveCmd(cmdBuf);
  299.     }
  300.     
  301.     if (memcmp("STAT", cmdBuf, strlen("STAT")) == 0)
  302.     {
  303.         StatCmd(cmdBuf);
  304.     }
  305.     
  306.     if (memcmp("X", cmdBuf, strlen("X")) == 0)
  307.     {
  308.         XCmd(cmdBuf);
  309.     }
  310. }
  311.  
  312. /***************************************************************************\
  313. *                                                                            *
  314. *    Routine:    InitServer                                                    *
  315. *                                                                            *
  316. *    Function:    Initialize the server.                                        *
  317. *                                                                            *
  318. *    Inputs:        None                                                        *
  319. *                                                                            *
  320. *    Outputs:    None                                                        *
  321. *                                                                            *
  322. \***************************************************************************/
  323.  
  324. InitServer()
  325. {
  326. long            freeBytes;
  327. OSErr            status, searching, found;
  328.  
  329.     searching = TRUE;
  330.     netNewsDrive = 0;
  331.     searching = TRUE;
  332.     found = FALSE;
  333.     while (searching)
  334.     {
  335.         status = GetVInfo(netNewsDrive, netNewsVolName, &netNewsVRefNum, &freeBytes);
  336.         if (netNewsDrive < MAX_DRIVES)
  337.         {
  338.             PtoCstr(netNewsVolName);
  339.             if ((memcmp("NETNEWS", netNewsVolName, strlen("NETNEWS")) == 0))
  340.             {
  341.                 searching = FALSE;
  342.                 found = TRUE;
  343.             }
  344.             else
  345.             {
  346.                 netNewsDrive++;
  347.             }
  348.         }
  349.         else
  350.         {
  351.             searching = FALSE;
  352.         }
  353.     }
  354.     if (found)
  355.     {
  356.         strcpy(xmtBuf, "201 NetNews/CD NNTP Mac Server - (no posting).\r\n");
  357.         SendTCP(&NNTP_PB, xmtBuf, (short)strlen(xmtBuf));
  358.         
  359.         strcpy (PathTransFSpec, netNewsVolName);
  360.         strcat (PathTransFSpec, ":LIB:PATHTRAN.;1");
  361.  
  362.         strcpy (activeFSpec, netNewsVolName);
  363.         strcat (activeFSpec, ":LIB:ACTIVE.;1");
  364.         return TRUE;
  365.     }
  366.     else
  367.     {
  368.         strcpy(msgText, "NetNews/CD Server: Can't find NETNEWS_CD volume.");
  369.         Report(msgText);
  370.         while (!Button())
  371.         {
  372.             WaitNextEvent( everyEvent, &gTheEvent, 0L, 0L);
  373.         }
  374.         strcpy(xmtBuf, "503 NetNews/CD Server: Can't find NETNEWS_CD volume.\r\n");
  375.         SendTCP(&NNTP_PB, xmtBuf, (short)strlen(xmtBuf));
  376.         return FALSE;
  377.     }
  378. }
  379.  
  380. /***************************************************************************\
  381. *                                                                            *
  382. *    Routine:    OpenMsgFile                                                    *
  383. *                                                                            *
  384. *    Function:    Open a message file.  If the file "xxx.;1" is not found,    *
  385. *                look for a file named "xxx.XRF;1 and use it as a pointer    *
  386. *                to the actual message file.  This supports articles that    *
  387. *                are posted to multiple groups (without duplicating the        *
  388. *                article text).                                                *
  389. *                                                                            *
  390. *    Inputs:        Article path and open mode.                                    *
  391. *                                                                            *
  392. *    Outputs:    Returns file reference if found, zero if not found.            *
  393. *                                                                            *
  394. \***************************************************************************/
  395.  
  396. OpenMsgFile(path, mode, msgFile)
  397. char        *path;
  398. char        *mode;
  399. FILE        **msgFile;
  400. {
  401. char        altPath[256], line[256];
  402. short        pathLength, lineLength;
  403. FILE        *xrfFile;
  404.  
  405.     *msgFile = fopen(path, mode);
  406.     if (*msgFile)
  407.     {
  408.         return;
  409.     }
  410.     else
  411.     {
  412.         pathLength = strlen(path);
  413.         strcpy(altPath, path);
  414.         strcpy(&altPath[pathLength-2], "XRF;1");
  415.         xrfFile = fopen(altPath, "r");
  416.         if(xrfFile)
  417.         {
  418.             if (GetLine(xrfFile, line))
  419.             {
  420.                 fclose(xrfFile);
  421.                 strcpy(altPath, netNewsVolName);
  422.                 strcat(altPath, ":SPOOL:");
  423.                 lineLength = strlen(line);
  424.                 line[lineLength-2] = 0;                    /* Delete <CR><LF> */
  425.                 strcat(altPath, line);
  426.                 strcat(altPath, ".;1");
  427.                 SlashToColon(altPath);
  428.                 *msgFile = fopen(altPath, mode);
  429.             }
  430.         }
  431.     }
  432. }
  433.  
  434. /***************************************************************************\
  435. *                                                                            *
  436. *    Routine:    ArticleCmd                                                    *
  437. *                                                                            *
  438. *    Function:    Respond to an 'ARTICLE' request.                            *
  439. *                                                                            *
  440. *    Inputs:        Request buffer.                                                *
  441. *                                                                            *
  442. *    Outputs:    None                                                        *
  443. *                                                                            *
  444. \***************************************************************************/
  445.  
  446. ArticleCmd(buf)
  447. char        *buf;
  448. {
  449. char        msg[16];
  450. char        msgPath[256], filename[32], line[256];
  451. FILE        *msgFile;
  452. short        stillReading;
  453.  
  454.     GetWord(buf, msg, 2);
  455.     strcpy(msgPath, CurrentGroupFSpec);
  456.     strcat(msgPath, ":");
  457.     GetMsgFilename(msg, filename);
  458.     strcat(msgPath, filename);
  459.  
  460. /*    Open the message file and send it to the requestor. */
  461.  
  462.     OpenMsgFile(msgPath, "r", &msgFile);
  463.     if (msgFile)
  464.     {
  465.         strcpy(xmtBuf, "220 <Message-ID???> head and body follow\r\n");
  466.         SendTCP(&NNTP_PB, xmtBuf, (short)strlen(xmtBuf));
  467.         stillReading = true;
  468.         while(stillReading)
  469.         {
  470.             if (GetLine(msgFile, line))
  471.             {
  472.                 SendTCP(&NNTP_PB, line, (short)strlen(line));
  473.             }
  474.             else
  475.             {
  476.                 stillReading = FALSE;
  477.             }
  478.         }
  479.         fclose(msgFile);
  480.         strcpy(xmtBuf, ".\r\n");
  481.         SendTCP(&NNTP_PB, xmtBuf, (short)strlen(xmtBuf));
  482.     }
  483.     else
  484.     {
  485.         strcpy(xmtBuf, "503 program fault - command not performed\r\n");
  486.         SendTCP(&NNTP_PB, xmtBuf, (short)strlen(xmtBuf));
  487.     }
  488. }
  489.  
  490. /***************************************************************************\
  491. *                                                                            *
  492. *    Routine:    BodyCmd                                                        *
  493. *                                                                            *
  494. *    Function:    Respond to an 'BODY' request.                                *
  495. *                                                                            *
  496. *    Inputs:        Request buffer.                                                *
  497. *                                                                            *
  498. *    Outputs:    None                                                        *
  499. *                                                                            *
  500. \***************************************************************************/
  501.  
  502. BodyCmd(buf)
  503. char        *buf;
  504. {
  505. char        msg[16];
  506. char        msgPath[256], filename[32], line[256];
  507. FILE        *msgFile;
  508. short        stillReading, bodyFound;
  509.  
  510.     GetWord(buf, msg, 2);
  511.     strcpy(msgPath, CurrentGroupFSpec);
  512.     strcat(msgPath, ":");
  513.     GetMsgFilename(msg, filename);
  514.     strcat(msgPath, filename);
  515.  
  516. /*    Open the message file and send the Body portion to the requestor. */
  517.  
  518.     OpenMsgFile(msgPath, "r", &msgFile);
  519.     if (msgFile)
  520.     {
  521.         strcpy(xmtBuf, "222 ");
  522.         strcat(xmtBuf, msg);
  523.         strcat(xmtBuf, " <Message-ID ???> Article retrieved - body follows.\r\n");
  524.         SendTCP(&NNTP_PB, xmtBuf, (short)strlen(xmtBuf));
  525.         stillReading = true;
  526.         bodyFound = false;
  527.         while(stillReading)
  528.         {
  529.             if (GetLine(msgFile, line))
  530.             {
  531.                 if (bodyFound)
  532.                 {
  533.                     SendTCP(&NNTP_PB, line, (short)strlen(line));
  534.                 }
  535.                 if (strlen(line) < 3)
  536.                 {
  537.                     bodyFound = true;
  538.                 }
  539.             }
  540.             else
  541.             {
  542.                 stillReading = FALSE;
  543.             }
  544.         }
  545.         fclose(msgFile);
  546.         strcpy(xmtBuf, ".\r\n");
  547.         SendTCP(&NNTP_PB, xmtBuf, (short)strlen(xmtBuf));
  548.     }
  549.     else
  550.     {
  551.         strcpy(xmtBuf, "503 program fault - command not performed\r\n");
  552.         SendTCP(&NNTP_PB, xmtBuf, (short)strlen(xmtBuf));
  553.     }
  554. }
  555.  
  556. /***************************************************************************\
  557. *                                                                            *
  558. *    Routine:    GetActiveEntry                                                *
  559. *                                                                            *
  560. *    Function:    Locate and return an entry from the 'Active' file for        *
  561. *                the requested newsgroup.                                    *
  562. *                                                                            *
  563. *    Inputs:        Request buffer.                                                *
  564. *                                                                            *
  565. *    Outputs:    None                                                        *
  566. *                                                                            *
  567. \***************************************************************************/
  568.  
  569. GetActiveEntry(group, entry)
  570. char        *group, *entry;
  571. {
  572. FILE        *activeFile;
  573. short        stillReading;
  574. char        line[256];
  575. char        lastGroup[256];
  576. short        found;
  577.  
  578.     entry[0] = 0;
  579.     GetWord(lastActiveEntry, lastGroup, 1);
  580.     if (!strcmp (lastGroup, group))
  581.     {
  582.         strcpy(entry, lastActiveEntry);
  583.         return;
  584.     }
  585.     activeFile = fopen(activeFSpec, "r");
  586.     if (activeFile)
  587.     {
  588.         stillReading = TRUE;
  589.         found = FALSE;
  590.         *entry = 0;
  591.         while(stillReading && !found)
  592.         {
  593.             if (GetLine(activeFile, line))
  594.             {
  595.                 if (!memcmp(line, group, strlen(group)))
  596.                 {
  597.                     strcpy(entry, line);
  598.                     found = TRUE;
  599.                 }
  600.             }
  601.             else
  602.             {
  603.                 stillReading = FALSE;
  604.             }
  605.         }
  606.         fclose(activeFile);
  607.         strcpy(lastActiveEntry, entry);
  608.         return found;
  609.     }
  610.     else
  611.     {
  612.         return false;
  613.     }
  614. }
  615.  
  616. /***************************************************************************\
  617. *                                                                            *
  618. *    Routine:    GetGroupInfo                                                *
  619. *                                                                            *
  620. *    Function:    Format the 'GROUP' request response.                        *
  621. *                                                                            *
  622. *    Inputs:        Group requested and response buffer.                        *
  623. *                                                                            *
  624. *    Outputs:    None                                                        *
  625. *                                                                            *
  626. \***************************************************************************/
  627.  
  628. GetGroupInfo(group, groupInfo)
  629. char        *group, *groupInfo;
  630. {
  631. char        first[16], last[16], msgs[16];
  632. char        activeEntry[256];
  633. long        numFirst, numLast, numMsgs;
  634. char        *ptr;
  635.  
  636. /* Active file format:    "news.admin 00001002 01000 y"    */
  637. /* Reply format:        "211 3 01000 00001002 news.admin\r\n"    */
  638.  
  639.     if (GetActiveEntry(group, activeEntry))
  640.     {
  641.         GetWord(activeEntry, last, 2);
  642.         GetWord(activeEntry, first, 3);
  643.         numFirst = strtol(first, &ptr, 10);
  644.         numLast = strtol(last, &ptr, 10);
  645.         numMsgs = numLast - numFirst + 1;
  646.         sprintf (msgs, "%ld", numMsgs);
  647.         sprintf (first, "%ld", numFirst);
  648.         sprintf (last, "%ld", numLast);
  649.         RememberGroup(group);
  650.     
  651.         strcpy(groupInfo, "211 ");
  652.         strcat(groupInfo, msgs);
  653.         strcat(groupInfo, " ");
  654.         strcat(groupInfo, first);
  655.         strcat(groupInfo, " ");
  656.         strcat(groupInfo, last);
  657.         strcat(groupInfo, " ");
  658.         strcat(groupInfo, group);
  659.         strcat(groupInfo, "\r\n");
  660.         return true;
  661.     }
  662.     else
  663.     {
  664.         return false;
  665.     }
  666. }
  667.  
  668. /***************************************************************************\
  669. *                                                                            *
  670. *    Routine:    SlashToColon                                                *
  671. *                                                                            *
  672. *    Function:    Change all occurances of '/' to ':' for Macintosh style        *
  673. *                folder heirarchy paths.                                        *
  674. *                                                                            *
  675. *    Inputs:        Word to be scanned.                                            *
  676. *                                                                            *
  677. *    Outputs:    Updated word.                                                *
  678. *                                                                            *
  679. \***************************************************************************/
  680.  
  681. SlashToColon(word)
  682. char        *word;
  683. {
  684. short        i;
  685. char        *src;
  686.  
  687.     src = word;
  688.     for(i=0; i<strlen(word); i++)
  689.     {
  690.         if (*src == '/')
  691.         {
  692.             *src = ':';
  693.         }
  694.         src++;
  695.     }
  696. }
  697.  
  698. /***************************************************************************\
  699. *                                                                            *
  700. *    Routine:    TranslateGroup                                                *
  701. *                                                                            *
  702. *    Function:    Use the 'Pathtran' file to translate the Unix group name    *
  703. *                to the ISO filename.                                        *
  704. *                                                                            *
  705. *    Inputs:        Group                                                        *
  706. *                                                                            *
  707. *    Outputs:    CurrentGroupFSpec                                            *
  708. *                                                                            *
  709. \***************************************************************************/
  710.  
  711. TranslateGroup(group, isoName)
  712. char        *group, *isoName;
  713. {
  714. FILE            *transFile;
  715. short        stillReading;
  716. char        line[256];
  717.  
  718.     if (!strcmp(lastGroup, group))
  719.     {
  720.         strcpy(isoName, lastISOgroup);
  721.         return;
  722.     }
  723.     
  724.     transFile = fopen(PathTransFSpec, "r");
  725.     if (transFile)
  726.     {
  727.         stillReading = true;
  728.         *isoName = 0;
  729.         while(stillReading)
  730.         {
  731.             if (GetLine(transFile, line))
  732.             {
  733.                 if (!memcmp(line, group, strlen(group)))
  734.                 {
  735.                     GetWord(line, isoName, 2);
  736.                     SlashToColon(isoName);
  737.                     stillReading = FALSE;
  738.                 }
  739.             }
  740.             else
  741.             {
  742.                 stillReading = FALSE;
  743.             }
  744.         }
  745.         fclose(transFile);
  746.         strcpy(lastISOgroup, isoName);
  747.     }
  748.     else
  749.     {
  750.         strcpy(xmtBuf, "503 program fault - command not performed\r\n");
  751.         SendTCP(&NNTP_PB, xmtBuf, (short)strlen(xmtBuf));
  752.     }
  753. }
  754.  
  755. /***************************************************************************\
  756. *                                                                            *
  757. *    Routine:    RememberGroup                                                *
  758. *                                                                            *
  759. *    Function:    Remember which group is current.                            *
  760. *                                                                            *
  761. *    Inputs:        Group                                                        *
  762. *                                                                            *
  763. *    Outputs:    CurrentGroupFSpec                                            *
  764. *                                                                            *
  765. \***************************************************************************/
  766.  
  767. RememberGroup(group)
  768. char        *group;
  769. {
  770. char        isoName[256];
  771.  
  772.     strcpy(CurrentGroupFSpec, netNewsVolName);
  773.     strcat(CurrentGroupFSpec, ":SPOOL:");
  774.     TranslateGroup(group, isoName);
  775.     strcat(CurrentGroupFSpec, isoName);
  776.     strcpy(lastGroup, group);
  777. }
  778.  
  779. /***************************************************************************\
  780. *                                                                            *
  781. *    Routine:    GroupCmd                                                    *
  782. *                                                                            *
  783. *    Function:    Respond to a 'GROUP' request.                                *
  784. *                                                                            *
  785. *    Inputs:        Request buffer.                                                *
  786. *                                                                            *
  787. *    Outputs:    None                                                        *
  788. *                                                                            *
  789. \***************************************************************************/
  790.  
  791. GroupCmd(buf)
  792. char        *buf;
  793. {
  794. char        group[256], groupInfo[256];
  795.  
  796.     GetWord(buf, group, 2);
  797.     if (GetGroupInfo(group, groupInfo))
  798.     {
  799.         SendTCP(&NNTP_PB, groupInfo, (short)strlen(groupInfo));
  800.     }
  801.     else
  802.     {
  803.         strcpy(xmtBuf, "411 no such news group\r\n");
  804.         SendTCP(&NNTP_PB, xmtBuf, (short)strlen(xmtBuf));
  805.     }
  806. }
  807.  
  808. /***************************************************************************\
  809. *                                                                            *
  810. *    Routine:    HeadCmd                                                        *
  811. *                                                                            *
  812. *    Function:    Respond to a 'HEAD' request.                                *
  813. *                                                                            *
  814. *    Inputs:        Request buffer.                                                *
  815. *                                                                            *
  816. *    Outputs:    None                                                        *
  817. *                                                                            *
  818. \***************************************************************************/
  819.  
  820. HeadCmd(buf)
  821. char        *buf;
  822. {
  823. char        msg[16];
  824. char        msgPath[256], filename[32], line[256];
  825. FILE        *msgFile;
  826. short        stillReading;
  827.  
  828.     GetWord(buf, msg, 2);
  829.     strcpy(msgPath, CurrentGroupFSpec);
  830.     strcat(msgPath, ":");
  831.     GetMsgFilename(msg, filename);
  832.     strcat(msgPath, filename);
  833.  
  834. /*    Open the message file and send the header portion to the requestor. */
  835.  
  836.     OpenMsgFile(msgPath, "r", &msgFile);
  837.     if (msgFile)
  838.     {
  839.         strcpy(xmtBuf, "221 ");
  840.         strcat(xmtBuf, msg);
  841.         strcat(xmtBuf, " <Message-ID ???> Article retrieved, header follows\r\n");
  842.         SendTCP(&NNTP_PB, xmtBuf, (short)strlen(xmtBuf));
  843.         stillReading = true;
  844.         while(stillReading)
  845.         {
  846.             if (GetLine(msgFile, line))
  847.             {
  848.                 if (strlen(line) < 3)
  849.                 {
  850.                     stillReading = FALSE;
  851.                 }
  852.                 else
  853.                 {
  854.                     SendTCP(&NNTP_PB, line, (short)strlen(line));
  855.                 }
  856.             }
  857.             else
  858.             {
  859.                 stillReading = FALSE;
  860.             }
  861.         }
  862.         fclose(msgFile);
  863.         strcpy(xmtBuf, ".\r\n");
  864.         SendTCP(&NNTP_PB, xmtBuf, (short)strlen(xmtBuf));
  865.     }
  866.     else
  867.     {
  868.         strcpy(xmtBuf, "503 program fault - command not performed\r\n");
  869.         SendTCP(&NNTP_PB, xmtBuf, (short)strlen(xmtBuf));
  870.     }
  871. }
  872.  
  873. /***************************************************************************\
  874. *                                                                            *
  875. *    Routine:    HelpCmd                                                        *
  876. *                                                                            *
  877. *    Function:    Respond to a 'HELP' request.                                *
  878. *                                                                            *
  879. *    Inputs:        Request buffer.                                                *
  880. *                                                                            *
  881. *    Outputs:    None                                                        *
  882. *                                                                            *
  883. \***************************************************************************/
  884.  
  885. HelpCmd(buf)
  886. char        *buf;
  887. {
  888.     strcpy(xmtBuf, "100 Help text follows.\r\n");
  889.     SendTCP(&NNTP_PB, xmtBuf, (short)strlen(xmtBuf));
  890.     strcpy(xmtBuf, "NetNews/CD NNTP Mac Server - (no posting).\r\n");
  891.     SendTCP(&NNTP_PB, xmtBuf, (short)strlen(xmtBuf));
  892.     strcpy(xmtBuf, "Version 1.0\r\n");
  893.     SendTCP(&NNTP_PB, xmtBuf, (short)strlen(xmtBuf));
  894.     strcpy(xmtBuf, ".\r\n");
  895.     SendTCP(&NNTP_PB, xmtBuf, (short)strlen(xmtBuf));
  896. }
  897.  
  898. /***************************************************************************\
  899. *                                                                            *
  900. *    Routine:    IhaveCmd                                                    *
  901. *                                                                            *
  902. *    Function:    Respond to a 'IHAVE' request.                                *
  903. *                                                                            *
  904. *    Inputs:        Request buffer.                                                *
  905. *                                                                            *
  906. *    Outputs:    None                                                        *
  907. *                                                                            *
  908. \***************************************************************************/
  909.  
  910. IhaveCmd(buf)
  911. char        *buf;
  912. {
  913.     strcpy(xmtBuf, "435 - article not wanted, do not send it.\r\n");
  914.     SendTCP(&NNTP_PB, xmtBuf, (short)strlen(xmtBuf));
  915. }
  916.  
  917. /***************************************************************************\
  918. *                                                                            *
  919. *    Routine:    LastCmd                                                        *
  920. *                                                                            *
  921. *    Function:    Respond to a 'LAST' request.                                *
  922. *                                                                            *
  923. *    Inputs:        Request buffer.                                                *
  924. *                                                                            *
  925. *    Outputs:    None                                                        *
  926. *                                                                            *
  927. \***************************************************************************/
  928.  
  929. LastCmd(buf)
  930. char        *buf;
  931. {
  932.     strcpy(xmtBuf, "223 - article retrieved - request text seperately.\r\n");
  933.     SendTCP(&NNTP_PB, xmtBuf, (short)strlen(xmtBuf));
  934. }
  935.  
  936. /***************************************************************************\
  937. *                                                                            *
  938. *    Routine:    GetLine                                                        *
  939. *                                                                            *
  940. *    Function:    Reads a line of data from a file.                            *
  941. *                                                                            *
  942. *    Inputs:        FILE pointer and input buffer.                                *
  943. *                                                                            *
  944. *    Outputs:    A line of data from the specified file.                        *
  945. *                                                                            *
  946. \***************************************************************************/
  947.  
  948. GetLine(file, buf)
  949. FILE        *file;
  950. char        *buf;
  951. {
  952. short        c;
  953. short        validData;
  954. char        *dst;
  955.  
  956.     dst = buf;
  957.     c = fgetc(file);
  958.     if (c == EOF)
  959.     {
  960.         validData = FALSE;
  961.     }
  962.     else
  963.     {
  964.         validData = TRUE;
  965.     }
  966.     while ((c!= EOF) && (c!= LF))
  967.     {
  968.         *dst++ = c;
  969.         c = fgetc(file);
  970.     }
  971.     *dst++ = CR;
  972.     *dst++ = LF;
  973.     *dst++ = 0;
  974.     return validData;
  975. }
  976.  
  977. /***************************************************************************\
  978. *                                                                            *
  979. *    Routine:    ListCmd                                                        *
  980. *                                                                            *
  981. *    Function:    Respond to a 'LIST' request.                                *
  982. *                                                                            *
  983. *    Inputs:        Request buffer.                                                *
  984. *                                                                            *
  985. *    Outputs:    None                                                        *
  986. *                                                                            *
  987. \***************************************************************************/
  988.  
  989. ListCmd(buf)
  990. char        *buf;
  991. {
  992. FILE        *activeFile;
  993. short        stillReading;
  994.  
  995.     strcpy(xmtBuf, "215 list of newsgroups follow\r\n");
  996.     SendTCP(&NNTP_PB, xmtBuf, (short)strlen(xmtBuf));
  997.     activeFile = fopen(activeFSpec, "r");
  998.     if (activeFile)
  999.     {
  1000.         stillReading = true;
  1001.         while(stillReading)
  1002.         {
  1003.             if (GetLine(activeFile, xmtBuf))
  1004.             {
  1005.                 SendTCP(&NNTP_PB, xmtBuf, (short)strlen(xmtBuf));
  1006.             }
  1007.             else
  1008.             {
  1009.                 stillReading = FALSE;
  1010.             }
  1011.         }
  1012.         fclose(activeFile);
  1013.         strcpy(xmtBuf, ".\r\n");
  1014.         SendTCP(&NNTP_PB, xmtBuf, (short)strlen(xmtBuf));
  1015.     }
  1016.     else
  1017.     {
  1018.         strcpy(xmtBuf, "503 program fault - command not performed\r\n");
  1019.         SendTCP(&NNTP_PB, xmtBuf, (short)strlen(xmtBuf));
  1020.     }
  1021. }
  1022.  
  1023. /***************************************************************************\
  1024. *                                                                            *
  1025. *    Routine:    NewGroupsCmd                                                *
  1026. *                                                                            *
  1027. *    Function:    Respond to a 'NEWGROUPS' request.                            *
  1028. *                                                                            *
  1029. *    Inputs:        Request buffer.                                                *
  1030. *                                                                            *
  1031. *    Outputs:    None                                                        *
  1032. *                                                                            *
  1033. \***************************************************************************/
  1034.  
  1035. NewGroupsCmd(buf)
  1036. char        *buf;
  1037. {
  1038.     strcpy(xmtBuf, "231 list of new newsgroups follows.\r\n");
  1039.     SendTCP(&NNTP_PB, xmtBuf, (short)strlen(xmtBuf));
  1040.     strcpy(xmtBuf, ".\r\n");
  1041.     SendTCP(&NNTP_PB, xmtBuf, (short)strlen(xmtBuf));
  1042. }
  1043.  
  1044. /***************************************************************************\
  1045. *                                                                            *
  1046. *    Routine:    NewNewsCmd                                                    *
  1047. *                                                                            *
  1048. *    Function:    Respond to a 'NEWNEWS' request.                                *
  1049. *                                                                            *
  1050. *    Inputs:        Request buffer.                                                *
  1051. *                                                                            *
  1052. *    Outputs:    None                                                        *
  1053. *                                                                            *
  1054. \***************************************************************************/
  1055.  
  1056. NewNewsCmd(buf)
  1057. char        *buf;
  1058. {
  1059.     strcpy(xmtBuf, "230 list of new articles by message-id follows.\r\n");
  1060.     SendTCP(&NNTP_PB, xmtBuf, (short)strlen(xmtBuf));
  1061.     strcpy(xmtBuf, ".\r\n");
  1062.     SendTCP(&NNTP_PB, xmtBuf, (short)strlen(xmtBuf));
  1063. }
  1064.  
  1065. /***************************************************************************\
  1066. *                                                                            *
  1067. *    Routine:    NextCmd                                                        *
  1068. *                                                                            *
  1069. *    Function:    Respond to a 'NEXT' request.                                *
  1070. *                                                                            *
  1071. *    Inputs:        Request buffer.                                                *
  1072. *                                                                            *
  1073. *    Outputs:    None                                                        *
  1074. *                                                                            *
  1075. \***************************************************************************/
  1076.  
  1077. NextCmd(buf)
  1078. char        *buf;
  1079. {
  1080.     strcpy(xmtBuf, "223 - article retrieved - request text seperately.\r\n");
  1081.     SendTCP(&NNTP_PB, xmtBuf, (short)strlen(xmtBuf));
  1082. }
  1083.  
  1084. /***************************************************************************\
  1085. *                                                                            *
  1086. *    Routine:    PostCmd                                                        *
  1087. *                                                                            *
  1088. *    Function:    Respond to a 'POST' request.                                *
  1089. *                                                                            *
  1090. *    Inputs:        Request buffer.                                                *
  1091. *                                                                            *
  1092. *    Outputs:    None                                                        *
  1093. *                                                                            *
  1094. \***************************************************************************/
  1095.  
  1096. PostCmd(buf)
  1097. char        *buf;
  1098. {
  1099.     strcpy(xmtBuf, "440 NetNews NNTP Local Mac Server - posting not allowed.\r\n");
  1100.     SendTCP(&NNTP_PB, xmtBuf, (short)strlen(xmtBuf));
  1101. }
  1102.  
  1103. /***************************************************************************\
  1104. *                                                                            *
  1105. *    Routine:    QuitCmd                                                        *
  1106. *                                                                            *
  1107. *    Function:    Respond to a 'QUIT' request.                                *
  1108. *                                                                            *
  1109. *    Inputs:        Request buffer.                                                *
  1110. *                                                                            *
  1111. *    Outputs:    None                                                        *
  1112. *                                                                            *
  1113. \***************************************************************************/
  1114.  
  1115. QuitCmd(buf)
  1116. char        *buf;
  1117. {
  1118.     strcpy(xmtBuf, "205 NetNews NNTP Local Mac Server closing connection.  Goodbye.\r\n");
  1119.     SendTCP(&NNTP_PB, xmtBuf, (short)strlen(xmtBuf));
  1120.     TerminateSession(NNTP_PB.tcpStream);
  1121.     sessionActive = FALSE;
  1122. }
  1123.  
  1124. /***************************************************************************\
  1125. *                                                                            *
  1126. *    Routine:    SlaveCmd                                                    *
  1127. *                                                                            *
  1128. *    Function:    Respond to a 'SLAVE' request.                                *
  1129. *                                                                            *
  1130. *    Inputs:        Request buffer.                                                *
  1131. *                                                                            *
  1132. *    Outputs:    None                                                        *
  1133. *                                                                            *
  1134. \***************************************************************************/
  1135.  
  1136. SlaveCmd(buf)
  1137. char        *buf;
  1138. {
  1139.     strcpy(xmtBuf, "202 - slave status noted.\r\n");
  1140.     SendTCP(&NNTP_PB, xmtBuf, (short)strlen(xmtBuf));
  1141. }
  1142.  
  1143. /***************************************************************************\
  1144. *                                                                            *
  1145. *    Routine:    StatCmd                                                        *
  1146. *                                                                            *
  1147. *    Function:    Respond to a 'STAT' request.                                *
  1148. *                                                                            *
  1149. *    Inputs:        Request buffer.                                                *
  1150. *                                                                            *
  1151. *    Outputs:    None                                                        *
  1152. *                                                                            *
  1153. \***************************************************************************/
  1154.  
  1155. StatCmd(buf)
  1156. char        *buf;
  1157. {
  1158.     strcpy(xmtBuf, "223 - article retrieved - request text seperately.\r\n");
  1159.     SendTCP(&NNTP_PB, xmtBuf, (short)strlen(xmtBuf));
  1160. }
  1161.  
  1162. /***************************************************************************\
  1163. *                                                                            *
  1164. *    Routine:    GetMsgFilename                                                *
  1165. *                                                                            *
  1166. *    Function:    Convert a message number string to an ISO filename.            *
  1167. *                                                                            *
  1168. *    Inputs:        Message number (ASCII, possible leading zeros)                *
  1169. *                                                                            *
  1170. *    Outputs:    ISO filename                                                *
  1171. *                                                                            *
  1172. \***************************************************************************/
  1173.  
  1174. GetMsgFilename(msg, filename)
  1175. char        *msg, *filename;
  1176. {
  1177. char        *src, *dst;
  1178.  
  1179.     src = msg;
  1180.     dst = filename;
  1181.     while ((*src != 0) && (*src == '0'))
  1182.     {
  1183.         src++;
  1184.     }
  1185.     while (*src != 0)
  1186.     {
  1187.         *dst++ = *src++;
  1188.     }
  1189.     *dst++ = 0;
  1190.     strcat(filename, ".;1");
  1191. }
  1192.  
  1193. /***************************************************************************\
  1194. *                                                                            *
  1195. *    Routine:    GetSubject                                                    *
  1196. *                                                                            *
  1197. *    Function:    Retrieve the SUBJECT line from a specified message.            *
  1198. *                                                                            *
  1199. *    Inputs:        Message and subject buffer.                                    *
  1200. *                                                                            *
  1201. *    Outputs:    None                                                        *
  1202. *                                                                            *
  1203. \***************************************************************************/
  1204.  
  1205. GetSubject(msg, subject)
  1206. char        *msg, *subject;
  1207. {
  1208. char        msgPath[256], filename[32], line[256];
  1209. char        msgPart[256], *subjMatter;
  1210. FILE        *msgFile;
  1211. short        stillReading, found;
  1212.  
  1213.     found = FALSE;
  1214.     strcpy(subjMatter, "(None)\r\n");
  1215.     strcpy(msgPath, CurrentGroupFSpec);
  1216.     strcat(msgPath, ":");
  1217.     GetMsgFilename(msg, filename);
  1218.     strcat(msgPath, filename);
  1219.  
  1220. /*    Open the message file and find the SUBJECT line. */
  1221.  
  1222.     OpenMsgFile(msgPath, "r", &msgFile);
  1223.     if (msgFile)
  1224.     {
  1225.         stillReading = true;
  1226.         *subject = 0;
  1227.         while(stillReading)
  1228.         {
  1229.             if (GetLine(msgFile, line))
  1230.             {
  1231.                 GetWord(line, msgPart, 1);
  1232.                 if (!strcmp (msgPart, "Subject:"))
  1233.                 {
  1234.                     strcpy(subjMatter, &line[9]);
  1235.                     stillReading = FALSE;
  1236.                     found = TRUE;
  1237.                 }
  1238.             }
  1239.             else
  1240.             {
  1241.                 stillReading = FALSE;
  1242.             }
  1243.         }
  1244.         fclose(msgFile);
  1245.     }
  1246.     strcpy(subject, msg);
  1247.     strcat(subject, " ");
  1248.     strcat(subject, subjMatter);
  1249.     return found;
  1250. }
  1251.  
  1252. /***************************************************************************\
  1253. *                                                                            *
  1254. *    Routine:    XCmd                                                        *
  1255. *                                                                            *
  1256. *    Function:    Respond to any Xxxx (extension) request.                    *
  1257. *                XHDR is the only extension supported.                        *
  1258. *                                                                            *
  1259. *    Inputs:        Request buffer.                                                *
  1260. *                                                                            *
  1261. *    Outputs:    None                                                        *
  1262. *                                                                            *
  1263. \***************************************************************************/
  1264.  
  1265. XCmd(buf)                /* "XHDR SUBJECT first-last" */
  1266. char        *buf;
  1267. {
  1268. long        i, cnt, first, last;
  1269. char        msg[16], firstLast[32], subject[256];
  1270. char        *ptr;
  1271.  
  1272.     if (memcmp("XHDR SUBJECT", buf, strlen("XHDR SUBJECT")) == 0)
  1273.     {
  1274.         strcpy(xmtBuf, "221 Subject fields follow.\r\n");
  1275.         SendTCP(&NNTP_PB, xmtBuf, (short)strlen(xmtBuf));
  1276.  
  1277.         GetWord(buf, firstLast, 3);
  1278.         first = strtol(firstLast, &ptr, 10);
  1279.         ptr++;
  1280.         last = strtol(ptr, &ptr, 10);
  1281.         if (last < first)
  1282.         {
  1283.             last = first;
  1284.         }
  1285.         for(i=first; i<=last; i++)
  1286.         {
  1287.             sprintf (msg, "%ld", i);
  1288.             if (GetSubject(msg, subject))
  1289.             {
  1290.                 SendTCP(&NNTP_PB, subject, (short)strlen(subject));
  1291.             }
  1292.         }
  1293.         strcpy(xmtBuf, ".\r\n");
  1294.         SendTCP(&NNTP_PB, xmtBuf, (short)strlen(xmtBuf));
  1295.     }
  1296.     else
  1297.     {
  1298.         strcpy(xmtBuf, "500 Command not recognized.\r\n");
  1299.         SendTCP(&NNTP_PB, xmtBuf, (short)strlen(xmtBuf));
  1300.     }
  1301. }
  1302.  
  1303. /***************************************************************************\
  1304. *                                                                            *
  1305. *    Routine:    ToolBoxInit                                                    *
  1306. *                                                                            *
  1307. *    Function:    Macintosh toolbox initialization.                            *
  1308. *                                                                            *
  1309. *    Inputs:        None                                                        *
  1310. *                                                                            *
  1311. *    Outputs:    None                                                        *
  1312. *                                                                            *
  1313. \***************************************************************************/
  1314.  
  1315. ToolBoxInit()
  1316. {
  1317.     InitGraf( &thePort );
  1318.     InitFonts();
  1319.     FlushEvents( everyEvent, REMOVE_ALL_EVENTS );
  1320.     InitWindows();
  1321.     InitMenus();
  1322.     TEInit();
  1323.     InitDialogs( NIL_POINTER );
  1324.     InitCursor();
  1325. }
  1326.  
  1327. /***************************************************************************\
  1328. *                                                                            *
  1329. *    Routine:    MenuBarInit                                                    *
  1330. *                                                                            *
  1331. *    Function:    Menu Bar initialization.                                    *
  1332. *                                                                            *
  1333. *    Inputs:        None                                                        *
  1334. *                                                                            *
  1335. *    Outputs:    None                                                        *
  1336. *                                                                            *
  1337. \***************************************************************************/
  1338.  
  1339. MenuBarInit()
  1340. {
  1341.     Handle        myMenuBar;
  1342.  
  1343.     if ((myMenuBar = GetNewMBar(BASE_RES_ID)) == NIL_POINTER)
  1344.         ErrorHandler(NO_MBAR);
  1345.     SetMenuBar(myMenuBar);
  1346.     if ((gAppleMenu = GetMHandle(APPLE_MENU_ID)) == NIL_POINTER)
  1347.         ErrorHandler(NO_MENU);
  1348.     if ((gEditMenu = GetMHandle(EDIT_MENU_ID)) == NIL_POINTER)
  1349.         ErrorHandler(NO_MENU);
  1350.  
  1351.     AddResMenu(gAppleMenu, 'DRVR');
  1352.     DrawMenuBar();
  1353. }
  1354.  
  1355. /***************************************************************************\
  1356. *                                                                            *
  1357. *    Routine:    TCPInit                                                        *
  1358. *                                                                            *
  1359. *    Function:    MacTCP initialization.                                        *
  1360. *                                                                            *
  1361. *    Inputs:        None                                                        *
  1362. *                                                                            *
  1363. *    Outputs:    None                                                        *
  1364. *                                                                            *
  1365. \***************************************************************************/
  1366.  
  1367. TCPInit()
  1368. {
  1369. char                tcpDriver[32];
  1370. OSErr                openStatus;
  1371.     
  1372.     strcpy(tcpDriver, ".ipp");
  1373.     CtoPstr(tcpDriver);
  1374.     openStatus = OpenDriver(&tcpDriver, &TCP_DriverRefNum);
  1375.     if (openStatus != noErr)
  1376.     {
  1377.         strcpy(msgText, "NNTP Server: TCP OpenDriver failed!");
  1378.         Report(msgText);
  1379.     }
  1380. }
  1381.  
  1382. /***************************************************************************\
  1383. *                                                                            *
  1384. *    Routine:    CleanUp                                                        *
  1385. *                                                                            *
  1386. *    Function:    Cleanup between sessions.                                    *
  1387. *                                                                            *
  1388. *    Inputs:        None                                                        *
  1389. *                                                                            *
  1390. *    Outputs:    None                                                        *
  1391. *                                                                            *
  1392. \***************************************************************************/
  1393.  
  1394. CleanUp()
  1395. {
  1396.     TerminateSession(NNTP_PB.tcpStream);
  1397. }
  1398.  
  1399. /***************************************************************************\
  1400. *                                                                            *
  1401. *    Routine:    HandleEvent                                                    *
  1402. *                                                                            *
  1403. *    Function:    Handle mouse and keyboard events.                            *
  1404. *                                                                            *
  1405. *    Inputs:        None                                                        *
  1406. *                                                                            *
  1407. *    Outputs:    None                                                        *
  1408. *                                                                            *
  1409. \***************************************************************************/
  1410.  
  1411. HandleEvent()
  1412. {
  1413.     char    theChar;
  1414.  
  1415.     WaitNextEvent( everyEvent, &gTheEvent, 0L, 0L);
  1416.  
  1417.     switch ( gTheEvent.what )
  1418.     {
  1419.         case mouseDown: 
  1420.             HandleMouseDown();
  1421.             break;
  1422.         case keyDown:
  1423.         case autoKey:
  1424.             theChar = gTheEvent.message & charCodeMask;
  1425.             if (( gTheEvent.modifiers & cmdKey ) != 0)
  1426.             {
  1427.                 AdjustMenus(); 
  1428.                 HandleMenuChoice( MenuKey( theChar ) );
  1429.             }
  1430.             break;
  1431.         case updateEvt:
  1432.             break;
  1433.     }
  1434. }
  1435.  
  1436. /***************************************************************************\
  1437. *                                                                            *
  1438. *    Routine:    HandleMouseDown                                                *
  1439. *                                                                            *
  1440. *    Function:    Handle mouse events.                                        *
  1441. *                                                                            *
  1442. *    Inputs:        None                                                        *
  1443. *                                                                            *
  1444. *    Outputs:    None                                                        *
  1445. *                                                                            *
  1446. \***************************************************************************/
  1447.  
  1448. HandleMouseDown()
  1449. {
  1450.     WindowPtr    whichWindow;
  1451.     short int    thePart;
  1452.     long int    menuChoice, windSize;
  1453.     
  1454.     
  1455.     thePart = FindWindow( gTheEvent.where, &whichWindow );
  1456.     switch ( thePart )
  1457.     {
  1458.         case inMenuBar:
  1459.             AdjustMenus();
  1460.             menuChoice = MenuSelect( gTheEvent.where );
  1461.             HandleMenuChoice( menuChoice );
  1462.             break;
  1463.         case inSysWindow: 
  1464.             SystemClick( &gTheEvent, whichWindow );
  1465.             break;
  1466.         case inDrag: 
  1467.             break;
  1468.         case inGoAway: 
  1469.             break;
  1470.         case inContent:
  1471.             SelectWindow( whichWindow );
  1472.             break;
  1473.     }
  1474. }
  1475.  
  1476. /***************************************************************************\
  1477. *                                                                            *
  1478. *    Routine:    AdjustMenus                                                    *
  1479. *                                                                            *
  1480. *    Function:    Enable the Edit menu items as necessary.                    *
  1481. *                                                                            *
  1482. *    Inputs:        None                                                        *
  1483. *                                                                            *
  1484. *    Outputs:    None                                                        *
  1485. *                                                                            *
  1486. \***************************************************************************/
  1487.  
  1488. AdjustMenus()
  1489. {
  1490.     if (IsDAWindow( FrontWindow() ) )
  1491.     {
  1492.         EnableItem(gEditMenu, UNDO_ITEM );
  1493.         EnableItem(gEditMenu, CUT_ITEM );
  1494.         EnableItem(gEditMenu, COPY_ITEM );
  1495.         EnableItem(gEditMenu, PASTE_ITEM );
  1496.         EnableItem(gEditMenu, CLEAR_ITEM );
  1497.     }
  1498.     else
  1499.     {
  1500.         DisableItem(gEditMenu, UNDO_ITEM );
  1501.         DisableItem(gEditMenu, CUT_ITEM );
  1502.         DisableItem(gEditMenu, COPY_ITEM );
  1503.         DisableItem(gEditMenu, PASTE_ITEM );
  1504.         DisableItem(gEditMenu, CLEAR_ITEM );
  1505.     }
  1506. }
  1507.  
  1508. /***************************************************************************\
  1509. *                                                                            *
  1510. *    Routine:    IsDAWindow                                                    *
  1511. *                                                                            *
  1512. *    Function:    Determine whether the top window is a Desk Accessory        *
  1513. *                window.                                                        *
  1514. *                                                                            *
  1515. *    Inputs:        WindowPtr                                                    *
  1516. *                                                                            *
  1517. *    Outputs:    TRUE if top window is a Desk Accessory window.                *
  1518. *                                                                            *
  1519. \***************************************************************************/
  1520.  
  1521. IsDAWindow( whichWindow )
  1522. WindowPtr    whichWindow;
  1523. {
  1524.     if ( whichWindow == NIL_POINTER )
  1525.         return( FALSE );
  1526.     else /* DA windows have negative windowKinds */
  1527.         return(((WindowPeek)whichWindow)->windowKind < 0);
  1528. }
  1529.  
  1530. /***************************************************************************\
  1531. *                                                                            *
  1532. *    Routine:    HandleMenuChoice                                            *
  1533. *                                                                            *
  1534. *    Function:    Interpret Menu selections, and call the appropriate            *
  1535. *                action routines.                                            *
  1536. *                                                                            *
  1537. *    Inputs:        Menu choice                                                    *
  1538. *                                                                            *
  1539. *    Outputs:    None                                                        *
  1540. *                                                                            *
  1541. \***************************************************************************/
  1542.  
  1543. HandleMenuChoice(menuChoice)
  1544. long int    menuChoice;
  1545. {
  1546.     int    theMenu;
  1547.     int    theItem;
  1548.     
  1549.     if (menuChoice != 0)
  1550.     {
  1551.         theMenu = HiWord(menuChoice);
  1552.         theItem = LoWord(menuChoice);
  1553.         switch (theMenu)
  1554.         {
  1555.             case APPLE_MENU_ID :
  1556.                 HandleAppleChoice( theItem );
  1557.                 break;
  1558.             case FILE_MENU_ID :
  1559.                 HandleFileChoice(theItem);
  1560.                 break;
  1561.             case EDIT_MENU_ID :
  1562.                 HandleEditChoice(theItem);
  1563.                 break;
  1564.         }
  1565.         HiliteMenu( 0 );
  1566.     }
  1567. }
  1568.  
  1569. /***************************************************************************\
  1570. *                                                                            *
  1571. *    Routine:    HandleAppleChoice                                            *
  1572. *                                                                            *
  1573. *    Function:    Interpret Apple Menu selections, and call the appropriate    *
  1574. *                action routines.                                            *
  1575. *                                                                            *
  1576. *    Inputs:        Menu choice                                                    *
  1577. *                                                                            *
  1578. *    Outputs:    None                                                        *
  1579. *                                                                            *
  1580. \***************************************************************************/
  1581.  
  1582. HandleAppleChoice(theItem)
  1583. int    theItem;
  1584. {
  1585.     Str255        accName;
  1586.     int            accNumber;
  1587.     
  1588.     switch (theItem)
  1589.     {
  1590.         case ABOUT_ITEM : 
  1591.             NoteAlert(ABOUT_ALERT, NIL_POINTER);
  1592.             break;
  1593.         default :
  1594.             GetItem(gAppleMenu, theItem, accName);
  1595.             accNumber = OpenDeskAcc(accName);
  1596.             break;
  1597.     }
  1598. }
  1599.  
  1600. /***************************************************************************\
  1601. *                                                                            *
  1602. *    Routine:    HandleFileChoice                                            *
  1603. *                                                                            *
  1604. *    Function:    Interpret File Menu selections, and call the appropriate    *
  1605. *                action routines.                                            *
  1606. *                                                                            *
  1607. *    Inputs:        Menu choice                                                    *
  1608. *                                                                            *
  1609. *    Outputs:    None                                                        *
  1610. *                                                                            *
  1611. \***************************************************************************/
  1612.  
  1613. HandleFileChoice(theItem)
  1614. int        theItem;
  1615. {
  1616.     WindowPtr    whichWindow;
  1617.     long    finalTicks;
  1618.     
  1619.     switch ( theItem )
  1620.     {
  1621.         case RESET_ITEM :
  1622.             break;
  1623.         case QUIT_ITEM :
  1624.             running = FALSE;
  1625.             break;
  1626.     }
  1627. }
  1628.  
  1629. /***************************************************************************\
  1630. *                                                                            *
  1631. *    Routine:    HandleEditChoice                                            *
  1632. *                                                                            *
  1633. *    Function:    Handle the Edit Menu Choice (only used by DAs)                *
  1634. *                                                                            *
  1635. *    Inputs:        Menu choice                                                    *
  1636. *                                                                            *
  1637. *    Outputs:    None                                                        *
  1638. *                                                                            *
  1639. \***************************************************************************/
  1640.  
  1641. HandleEditChoice(theItem)
  1642. int    theItem;
  1643. {
  1644.     SystemEdit(theItem - 1);
  1645. }
  1646.  
  1647. /***************************************************************************\
  1648. *                                                                            *
  1649. *    Routine:    ErrorHandler                                                *
  1650. *                                                                            *
  1651. *    Function:    Display a "Stop Alert'                                        *
  1652. *                                                                            *
  1653. *    Inputs:        Alert message to be displayed                                *
  1654. *                                                                            *
  1655. *    Outputs:    None                                                        *
  1656. *                                                                            *
  1657. \***************************************************************************/
  1658.  
  1659. ErrorHandler(stringNum)
  1660. int    stringNum;
  1661. {
  1662.     StringHandle    errorStringH;
  1663.     
  1664.     if ((errorStringH = GetString( stringNum ) ) == NIL_POINTER)
  1665.         ParamText(HOPELESSLY_FATAL_ERROR, NIL_STRING, NIL_STRING, NIL_STRING);
  1666.     else
  1667.     {
  1668.         HLock(errorStringH);
  1669.         ParamText(*errorStringH, NIL_STRING, NIL_STRING, NIL_STRING);
  1670.         HUnlock(errorStringH);
  1671.     }
  1672.     StopAlert(ERROR_ALERT_ID, NIL_POINTER);
  1673.     ExitToShell();
  1674. }
  1675.  
  1676. /***************************************************************************\
  1677. *                                                                            *
  1678. *    Routine:    CompletionRtn                                                *
  1679. *                                                                            *
  1680. *    Function:    I/O completion routine                                        *
  1681. *                                                                            *
  1682. *    Inputs:        None                                                        *
  1683. *                                                                            *
  1684. *    Outputs:    None                                                        *
  1685. *                                                                            *
  1686. \***************************************************************************/
  1687.  
  1688. CompletionRtn()
  1689. {
  1690.  
  1691. }
  1692.  
  1693. /***************************************************************************\
  1694. *                                                                            *
  1695. *    Routine:    ReceiveTCP                                                    *
  1696. *                                                                            *
  1697. *    Function:    TCP recieve routine                                            *
  1698. *                                                                            *
  1699. *    Inputs:        Parameter block, buffer, and length                            *
  1700. *                                                                            *
  1701. *    Outputs:    None                                                        *
  1702. *                                                                            *
  1703. \***************************************************************************/
  1704.  
  1705. ReceiveTCP(pb, buf, length)
  1706. TCPiopb            *pb;
  1707. char            *buf;
  1708. short            length;
  1709.  
  1710. {
  1711. OSErr            recvStatus;
  1712.  
  1713.     (*pb).ioCompletion = NIL;
  1714.     (*pb).csCode = TCPRcv;
  1715.     (*pb).csParam.receive.commandTimeoutValue = 0;
  1716.     (*pb).csParam.receive.rcvBuff = buf;
  1717.     (*pb).csParam.receive.rcvBuffLen = length;
  1718.     (*pb).csParam.receive.userDataPtr = NIL;
  1719.     recvStatus = PBControl(pb, TRUE);
  1720. }
  1721.  
  1722. /***************************************************************************\
  1723. *                                                                            *
  1724. *    Routine:    SendTCP                                                        *
  1725. *                                                                            *
  1726. *    Function:    TCP send routine                                            *
  1727. *                                                                            *
  1728. *    Inputs:        Parameter block, buffer, and length                            *
  1729. *                                                                            *
  1730. *    Outputs:    None                                                        *
  1731. *                                                                            *
  1732. \***************************************************************************/
  1733.  
  1734. SendTCP(pb, msg, length)
  1735. TCPiopb            *pb;
  1736. char            *msg;
  1737. short            length;
  1738.  
  1739. {
  1740. OSErr            sendStatus;
  1741.  
  1742.     (*pb).ioCompletion = NIL;
  1743.     (*pb).csCode = TCPSend;
  1744.     (*pb).csParam.send.ulpTimeoutValue = 0;
  1745.     (*pb).csParam.send.ulpTimeoutAction = 0;
  1746.     (*pb).csParam.send.validityFlags = 0x80;            /* ULP timeout        */
  1747.     (*pb).csParam.send.pushFlag = 1;                    /* Send Immediately    */
  1748.     (*pb).csParam.send.urgentFlag = 0;
  1749.     sendWDS.length1 = length;
  1750.     sendWDS.address1 = msg;
  1751.     sendWDS.length2 = 0;
  1752.     (*pb).csParam.send.wdsPtr = (Ptr) &sendWDS;
  1753.     (*pb).csParam.send.userDataPtr = NIL;
  1754.     sendStatus = PBControl(pb, TRUE);
  1755.     while ((*pb).ioResult == ioInProgress)
  1756.     {
  1757.         WaitNextEvent(everyEvent, &evt, 0, NIL);
  1758.     }
  1759. }
  1760.  
  1761. /***************************************************************************\
  1762. *                                                                            *
  1763. *    Routine:    PassiveOpen                                                    *
  1764. *                                                                            *
  1765. *    Function:    TCP passive open routine                                    *
  1766. *                                                                            *
  1767. *    Inputs:        Parameter block, TCP port                                    *
  1768. *                                                                            *
  1769. *    Outputs:    None                                                        *
  1770. *                                                                            *
  1771. \***************************************************************************/
  1772.  
  1773. PassiveOpen(pb, port)
  1774. TCPiopb            *pb;
  1775. int                port;
  1776. {
  1777.     OSErr                createStatus, passiveStatus;
  1778.  
  1779.     (*pb).ioCompletion = NIL;
  1780.     (*pb).ioCRefNum = TCP_DriverRefNum;
  1781.     (*pb).csCode = TCPCreate;
  1782.     (*pb).csParam.create.rcvBuff = NewPtr(TCPBufSize);
  1783.     (*pb).csParam.create.rcvBuffLen = TCPBufSize;
  1784.     (*pb).csParam.create.notifyProc = NIL;
  1785.     (*pb).csParam.create.userDataPtr = NIL;
  1786.     createStatus = PBControl(pb, FALSE);
  1787.     
  1788.     (*pb).ioCompletion = NIL;
  1789.     (*pb).ioCRefNum = TCP_DriverRefNum;
  1790.     (*pb).csCode = TCPPassiveOpen;
  1791.     (*pb).csParam.open.ulpTimeoutValue = 0;
  1792.     (*pb).csParam.open.ulpTimeoutAction = 0;
  1793.     (*pb).csParam.open.validityFlags = 0x80;            /* ULP timeout        */
  1794.     (*pb).csParam.open.commandTimeoutValue = 0;
  1795.     (*pb).csParam.open.remoteHost = 0;
  1796.     (*pb).csParam.open.remotePort = 0;
  1797.     (*pb).csParam.open.localPort = port;
  1798.     (*pb).csParam.open.tosFlags = 0x02;                    /* High Throughput    */
  1799.     (*pb).csParam.open.dontFrag = 0;                    /* OK to Fragment    */
  1800.     (*pb).csParam.open.timeToLive = 64;
  1801.     (*pb).csParam.open.security = 0;
  1802.     (*pb).csParam.open.optionCnt = 0;
  1803.     (*pb).csParam.open.userDataPtr = NIL;
  1804.     passiveStatus = PBControl(pb, TRUE);
  1805. }
  1806.  
  1807. /***************************************************************************\
  1808. *                                                                            *
  1809. *    Routine:    ActiveOpen                                                    *
  1810. *                                                                            *
  1811. *    Function:    TCP active open routine                                        *
  1812. *                                                                            *
  1813. *    Inputs:        Parameter block, TCP local port, TCP remote port            *
  1814. *                                                                            *
  1815. *    Outputs:    None                                                        *
  1816. *                                                                            *
  1817. \***************************************************************************/
  1818.  
  1819. ActiveOpen(pb, remHost, locPort, remPort)
  1820. TCPiopb            *pb;
  1821. long            remHost;
  1822. int                locPort, remPort;
  1823. {
  1824.     OSErr                createStatus, activeStatus;
  1825.  
  1826.     (*pb).ioCompletion = NIL;
  1827.     (*pb).ioCRefNum = TCP_DriverRefNum;
  1828.     (*pb).csCode = TCPCreate;
  1829.     (*pb).csParam.create.rcvBuff = NewPtr(TCPBufSize);
  1830.     (*pb).csParam.create.rcvBuffLen = TCPBufSize;
  1831.     (*pb).csParam.create.notifyProc = NIL;
  1832.     (*pb).csParam.create.userDataPtr = NIL;
  1833.     createStatus = PBControl(pb, FALSE);
  1834.     
  1835.     (*pb).ioCompletion = NIL;
  1836.     (*pb).ioCRefNum = TCP_DriverRefNum;
  1837.     (*pb).csCode = TCPActiveOpen;
  1838.     (*pb).csParam.open.ulpTimeoutValue = 0;
  1839.     (*pb).csParam.open.ulpTimeoutAction = 0;
  1840.     (*pb).csParam.open.validityFlags = 0x80;            /* ULP timeout        */
  1841.     (*pb).csParam.open.commandTimeoutValue = 0;
  1842.     (*pb).csParam.open.remoteHost = remHost;
  1843.     (*pb).csParam.open.remotePort = remPort;
  1844.     (*pb).csParam.open.localPort = locPort;
  1845.     (*pb).csParam.open.tosFlags = 0x02;                    /* High Throughput    */
  1846.     (*pb).csParam.open.dontFrag = 0;                    /* OK to Fragment    */
  1847.     (*pb).csParam.open.timeToLive = 64;
  1848.     (*pb).csParam.open.security = 0;
  1849.     (*pb).csParam.open.optionCnt = 0;
  1850.     (*pb).csParam.open.userDataPtr = NIL;
  1851.     activeStatus = PBControl(pb, TRUE);
  1852.     while ((*pb).ioResult == ioInProgress)
  1853.     {
  1854.         WaitNextEvent(everyEvent, &evt, 0, NIL);
  1855.     }
  1856.     if ((*pb).ioResult < 0)
  1857.     {
  1858.         strcpy(msgText, "NNTP Server: TCP Active Open failed!");
  1859.         Report(msgText);
  1860.     }
  1861. }
  1862.  
  1863. /***************************************************************************\
  1864. *                                                                            *
  1865. *    Routine:    RecieveStatus                                                *
  1866. *                                                                            *
  1867. *    Function:    Check the status of a TCP recieve, and report an            *
  1868. *                error if there was a problem.                                *
  1869. *                                                                            *
  1870. *    Inputs:        Parameter block                                                *
  1871. *                                                                            *
  1872. *    Outputs:    None                                                        *
  1873. *                                                                            *
  1874. \***************************************************************************/
  1875.  
  1876. RecieveStatus(pb)
  1877. TCPiopb            *pb;
  1878. {
  1879.     while ((*pb).ioResult == ioInProgress)
  1880.     {
  1881.         WaitNextEvent(everyEvent, &evt, 0, NIL);
  1882.     }
  1883.     if ((*pb).ioResult < 0)
  1884.     {
  1885.         strcpy(msgText, "NNTP Server: TCP Receive failed!");
  1886.         Report(msgText);
  1887.     }
  1888. }
  1889.  
  1890. /***************************************************************************\
  1891. *                                                                            *
  1892. *    Routine:    SendStatus                                                    *
  1893. *                                                                            *
  1894. *    Function:    Check the status of a TCP send, and report an                *
  1895. *                error if there was a problem.                                *
  1896. *                                                                            *
  1897. *    Inputs:        Parameter block                                                *
  1898. *                                                                            *
  1899. *    Outputs:    None                                                        *
  1900. *                                                                            *
  1901. \***************************************************************************/
  1902.  
  1903. SendStatus(pb)
  1904. TCPiopb            *pb;
  1905. {
  1906.     while ((*pb).ioResult == ioInProgress)
  1907.     {
  1908.         WaitNextEvent(everyEvent, &evt, 0, NIL);
  1909.     }
  1910.     if ((*pb).ioResult < 0)
  1911.         {
  1912.             strcpy(msgText, "NNTP Server: TCP Send failed!");
  1913.             Report(msgText);
  1914.         }
  1915. }
  1916.  
  1917. /***************************************************************************\
  1918. *                                                                            *
  1919. *    Routine:    TerminateSession                                            *
  1920. *                                                                            *
  1921. *    Function:    Shut down a TCP connection, and release the stream.            *
  1922. *                                                                            *
  1923. *    Inputs:        Stream                                                        *
  1924. *                                                                            *
  1925. *    Outputs:    None                                                        *
  1926. *                                                                            *
  1927. \***************************************************************************/
  1928.  
  1929. TerminateSession(stream)
  1930. StreamPtr        stream;
  1931. {
  1932. OSErr            releaseStatus, status;
  1933. TCPiopb            pb;
  1934. TCPiopb            statusPB;
  1935.  
  1936. /* Wait for transmitted data to complete. */
  1937.  
  1938.     status = noErr;
  1939.     statusPB.csParam.status.amtUnackedData = -1;
  1940.     while((statusPB.csParam.status.amtUnackedData != 0) && (status == noErr))
  1941.     {
  1942.         statusPB.ioCompletion = NIL;
  1943.         statusPB.ioCRefNum = TCP_DriverRefNum;
  1944.         statusPB.tcpStream = stream;
  1945.         statusPB.csCode = TCPStatus;
  1946.         status = PBControl(&statusPB, FALSE);
  1947.         WaitNextEvent( everyEvent, &gTheEvent, 0L, 0L);
  1948.     }
  1949.     
  1950. /* Close the connection. */
  1951.  
  1952.     pb.ioCompletion = NIL;
  1953.     pb.ioCRefNum = TCP_DriverRefNum;
  1954.     pb.tcpStream = stream;
  1955.     pb.csCode = TCPClose;
  1956.     releaseStatus = PBControl(&pb, TRUE);
  1957.     while (pb.ioResult == inProgress)
  1958.     {
  1959.         WaitNextEvent( everyEvent, &gTheEvent, 0L, 0L);
  1960.     }
  1961.     
  1962. /* Wait for the close to complete. */
  1963.  
  1964.     statusPB.csParam.status.connectionState = ESTABLISHED;
  1965.     status = noErr;
  1966.     while((statusPB.csParam.status.connectionState != CLOSED) && (status == noErr))
  1967.     {
  1968.         statusPB.ioCompletion = NIL;
  1969.         statusPB.ioCRefNum = TCP_DriverRefNum;
  1970.         statusPB.tcpStream = stream;
  1971.         statusPB.csCode = TCPStatus;
  1972.         status = PBControl(&statusPB, FALSE);
  1973.         WaitNextEvent( everyEvent, &gTheEvent, 0L, 0L);
  1974.     }
  1975.  
  1976. /* Release the stream. */
  1977.  
  1978.     pb.ioCompletion = NIL;
  1979.     pb.ioCRefNum = TCP_DriverRefNum;
  1980.     pb.tcpStream = stream;
  1981.     pb.csCode = TCPRelease;
  1982.     releaseStatus = PBControl(&pb, FALSE);
  1983. }
  1984.  
  1985. /***************************************************************************\
  1986. *                                                                            *
  1987. *    Routine:    TCPStatusCheck                                                *
  1988. *                                                                            *
  1989. *    Function:    Determine the state of a connection.                        *
  1990. *                                                                            *
  1991. *    Inputs:        Stream                                                        *
  1992. *                                                                            *
  1993. *    Outputs:    Connection state (see MacTCP documentation).                *
  1994. *                                                                            *
  1995. \***************************************************************************/
  1996.  
  1997. TCPStatusCheck(stream)
  1998. StreamPtr        stream;
  1999. {
  2000. OSErr            status;
  2001. TCPiopb            statusPB;
  2002.  
  2003.     statusPB.ioCompletion = NIL;
  2004.     statusPB.ioCRefNum = TCP_DriverRefNum;
  2005.     statusPB.tcpStream = stream;
  2006.     statusPB.csCode = TCPStatus;
  2007.     status = PBControl(&statusPB, FALSE);
  2008.     return statusPB.csParam.status.connectionState;
  2009. }
  2010.  
  2011. /***************************************************************************\
  2012. *                                                                            *
  2013. *    Routine:    Report                                                        *
  2014. *                                                                            *
  2015. *    Function:    Use the Notification Manager to report an error.            *
  2016. *                                                                            *
  2017. *    Inputs:        Error message.                                                *
  2018. *                                                                            *
  2019. *    Outputs:    Dialog box display.                                            *
  2020. *                                                                            *
  2021. \***************************************************************************/
  2022.  
  2023. Report(Err)
  2024. char        *Err;
  2025. {
  2026. OSErr            nmStatus;
  2027. NMRecPtr        errorNotification;
  2028. Ptr                sP;
  2029.  
  2030.     errorNotification = (NMRecPtr) NewPtr(sizeof(NMRec));
  2031.     (*errorNotification).qType = 8;
  2032.     (*errorNotification).nmMark = 0;
  2033.     (*errorNotification).nmIcon = NIL;
  2034.     (*errorNotification).nmSound = (Handle) -1;
  2035.     sP = NewPtr(MaxErrorString);
  2036.     strcpy(sP, Err);
  2037.     CtoPstr(sP);
  2038.     (*errorNotification).nmStr = (StringPtr) sP;
  2039.     (*errorNotification).nmResp = (ProcPtr) -1;
  2040.     (*errorNotification).nmRefCon = 0;
  2041.     
  2042.     nmStatus = NMInstall(errorNotification);
  2043.  
  2044. }
  2045.  
  2046. /***************************************************************************\
  2047. *                                                                            *
  2048. *    Routine:    GetWord                                                        *
  2049. *                                                                            *
  2050. *    Function:    Parse out a word from a line of text seperated by white        *
  2051. *                space (space, tab, <CR>, <LF>).                                *
  2052. *                                                                            *
  2053. *    Inputs:        Input buffer, result buffer, word number.                    *
  2054. *                                                                            *
  2055. *    Outputs:    Result word.                                                *
  2056. *                                                                            *
  2057. \***************************************************************************/
  2058.  
  2059. GetWord(buf, word, whichWord)
  2060. char        *buf, *word;
  2061. short        whichWord;
  2062. {
  2063. char        *src, *dst;
  2064. short        skip;
  2065.  
  2066.     src = buf;
  2067.     dst = word;
  2068.     skip = whichWord -1;
  2069.     while (skip > 0)
  2070.     {
  2071.         while ((*src == SPACE) || (*src == TAB))        /* Skip to a word. */
  2072.         {
  2073.             src++;
  2074.         }
  2075.         while ((*src != SPACE) && (*src != TAB))        /* Skip the word. */
  2076.         {
  2077.             src++;
  2078.         }
  2079.         skip--;
  2080.     }
  2081.     while ((*src == SPACE) || (*src == TAB))            /* Skip to start of word. */
  2082.     {
  2083.         src++;
  2084.     }
  2085.     while ((*src != SPACE) && (*src != TAB)                /* Copy the word. */
  2086.              && (*src != CR) && (*src != LF) && (*src != 0))
  2087.     {
  2088.         *dst++ = *src++;
  2089.     }
  2090.     *dst++ = 0;
  2091. }
  2092.  
  2093.  
  2094.  
  2095.